package com.cloud.sso.service;

import com.cloud.sso.common.exception.AppException;
import com.cloud.sso.common.page.AppPageInfo;
import com.cloud.sso.common.util.CollectionUtil;
import com.cloud.sso.common.util.SnowFlakeUtil;
import com.cloud.sso.dto.MenuQueryDto;
import com.cloud.sso.dto.MenuSaveDto;
import com.cloud.sso.entity.Application;
import com.cloud.sso.entity.SysMenu;
import com.cloud.sso.entity.SysRole;
import com.cloud.sso.entity.SysRoleMenu;
import com.cloud.sso.mapper.ApplicationMapper;
import com.cloud.sso.mapper.MenuMapper;
import com.cloud.sso.mapper.RoleMenuMapper;
import com.cloud.sso.oauth.obj.AppMenu;
import com.cloud.sso.vo.MenuTreeVo;
import com.cloud.sso.vo.MenuVo;
import com.cloud.sso.vo.RoleVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class MenuService {


    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private ApplicationMapper applicationMapper;


    public AppPageInfo query(MenuQueryDto queryDto) {
        queryDto.setStartIndex();

        List<SysMenu> menuList = menuMapper.queryMenuPage(queryDto);
        Integer count = menuMapper.getCount(queryDto);

        AppPageInfo pageInfo = new AppPageInfo(entityToVo(menuList), count, queryDto.getPageNum(), queryDto.getPageSize());

        return pageInfo;
    }

    public List<SysRoleMenu> queryRoleMenu(String roleId) {
        return roleMenuMapper.queryRoleMenu(roleId);
    }

    /**
     * 保存菜单
     *
     * @param saveDto
     */
    public void save(MenuSaveDto saveDto) {
        SysMenu sysMenu = new SysMenu();

        BeanUtils.copyProperties(saveDto, sysMenu);
        try {
            String path = buildMenuPath(sysMenu.getMenuCode(), sysMenu.getParentId());
            sysMenu.setPath(path);

            //设置菜单level
            if (saveDto.getParentId().equals("0")) {
                sysMenu.setLevel(1);
            } else {
                SysMenu parentMenu = menuMapper.selectById(saveDto.getParentId());
                if (parentMenu == null) {
                    throw new AppException("上级菜单不存在");
                }
                sysMenu.setLevel(parentMenu.getLevel() + 1);
            }

            if (saveDto.getId() == null) {

                Map<String, Object> map = new HashMap<>();
                map.put("menu_code", saveDto.getMenuCode());

                if (CollectionUtil.isNotNull(menuMapper.selectByMap(map))) {
                    throw new AppException("菜单code已经存在");
                } else {
                    sysMenu.setId(new SnowFlakeUtil().nextStringId());
                    menuMapper.insert(sysMenu);
                }

            } else {
                menuMapper.updateById(sysMenu);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

  /*  public List<AppMenu> queryRo(String roleId) {

        List<AppMenu> appMenus = new ArrayList<>();

        List<SysRoleMenu> sysRoleMenus = roleMenuMapper.queryRoleMenu(roleId);

        return appMenus;
    }
*/
    /**
     * 构建菜单path
     *
     * @param menuCode
     * @param parentId
     * @return
     */
    public String buildMenuPath(String menuCode, String parentId) {
        if (parentId == null || parentId.equals("0")) {
            return new StringBuilder("#").append(menuCode).toString();
        }
        SysMenu parentMenu = menuMapper.selectById(parentId);
        if (parentMenu == null) {
            throw new AppException("父级菜单不存在");
        }
        return new StringBuilder(parentMenu.getPath()).append("#").append(menuCode).toString();
    }

    /**
     * 删除菜单
     *
     * @param id *
     */
    public void delete(String id) {
        SysMenu sysMenu = menuMapper.selectById(id);
        if (sysMenu == null) {
            throw new AppException("菜单不存在");
        }

        if (CollectionUtil.isNotNull(roleMenuMapper.queryByMenu(id))) {
            throw new AppException("该菜单已经绑定角色，请先解绑菜单信息");
        }
        menuMapper.deleteById(id);
    }

    public List<MenuVo> subMenu(String appId, String parentId) {
        if (parentId == null || parentId.equals("0")) {
            parentId = "0";
        }
        Map<String, Object> param = new HashMap<>();
        param.put("app_id", appId);
        param.put("parent_id", parentId);

        return entityToVo(menuMapper.selectByMap(param));
    }

    public List<MenuVo> tree(String appId) {

        Map<String, Object> param = new HashMap<>();
        param.put("app_id", appId);
        try {

            List<SysMenu> menus = menuMapper.selectByMap(param);

            List<MenuVo> menuVos = entityToVo(menus);

            return buildTree(menuVos);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public List<MenuVo> buildTree(List<MenuVo> zoneList) {

        List<MenuVo> result = new ArrayList<>();

        for (MenuVo zone : zoneList) {

            if (zone.getParentId().equals("0")) {

                result.add(zone);
                setChildren(zoneList, zone);
            }

        }

        return result;

    }

    public void setChildren(List<MenuVo> list, MenuVo parent) {
        for (MenuVo zone : list) {
            if (parent.getId().equals(zone.getParentId())) {
                parent.getChildren().add(zone);
            }
        }

        if (parent.getChildren().isEmpty()) {
            return;
        }
        for (MenuVo zone : parent.getChildren()) {
            setChildren(list, zone);
        }

    }

    public MenuVo get(String id) {
        SysMenu sysMenu = menuMapper.selectById(id);

        if (sysMenu != null) {
            return entityToVo(new ArrayList<SysMenu>() {{
                add(sysMenu);
            }}).get(0);
        } else {
            return null;
        }

    }


    public List<MenuVo> entityToVo(List<SysMenu> menus) {
        List<MenuVo> menuVos = new ArrayList<>();
        if (menus == null) {
            return null;
        }

        menus.stream().forEach(e -> {
            MenuVo menuVo = new MenuVo();
            BeanUtils.copyProperties(e, menuVo);
            Application application = applicationMapper.selectById(e.getAppId());
            menuVo.setAppName(application != null ? application.getAppName() : "");
            if (e.getParentId().equals("0")) {
                menuVo.setParentMenuName("-");
            } else {
                SysMenu parentMenu = menuMapper.selectById(e.getParentId());
                menuVo.setParentMenuName(parentMenu != null ? parentMenu.getMenuName() : "-");
            }
            /*   menuVo.setLeaf(e.getLeaf().equals("1")? true : false);*/
            menuVos.add(menuVo);
        });

        return menuVos;
    }
}

